package com.wheel.autoconfigure.web.mvc.returnvaluehandler;/*
 * <h3>Title:ai-chiefcomplaint系统</h3>
 * <p>Copyright (c) 2021, wnfbx. All rights reserved.</p>
 * @author wnfbx
 */

import com.wheel.core.result.Result;
import com.wheel.core.utils.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.lang.Nullable;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * <dt>Description:ResultRequestResponseBodyMethodProcessor</dt>
 * <dd>自定义返回结果通用处理</dd>
 *
 * @author wnfbx
 * @version 1.0 <i>2021/8/5 19:14</i>
 * @since jdk1.7+
 */
public class ResultRequestResponseBodyMethodProcessor extends RequestResponseBodyMethodProcessor {

    private static final Logger log = LoggerFactory.getLogger(ResultRequestResponseBodyMethodProcessor.class);

    public ResultRequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters) {
        super(converters);
    }

    public ResultRequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters, ContentNegotiationManager manager) {
        super(converters, manager);
    }

    public ResultRequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters, List<Object> requestResponseBodyAdvice) {
        super(converters, requestResponseBodyAdvice);
    }

    public ResultRequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters, ContentNegotiationManager manager, List<Object> requestResponseBodyAdvice) {
        super(converters, manager, requestResponseBodyAdvice);
    }

    public static <T extends HandlerMethodReturnValueHandler> T mvcConfigurationRegister(Class<? extends HandlerMethodReturnValueHandler> target, T processor, RequestMappingHandlerAdapter adapter) {
        //不能修改 重置
        List<HandlerMethodReturnValueHandler> returnValueHandlers = adapter.getReturnValueHandlers();
        ArrayList<HandlerMethodReturnValueHandler> returnValueHandlerArrayList = new ArrayList<>();
        boolean replaced = false;
        for (HandlerMethodReturnValueHandler argumentResolver : returnValueHandlers) {
            if (target.isInstance(argumentResolver)) {
                replaced = true;
                Log.info(log, "自定义参数处理器{}代替系统默认处理器{}", processor.getClass().getName(), target.getName());
                returnValueHandlerArrayList.add(processor);
            } else {
                returnValueHandlerArrayList.add(argumentResolver);
            }
        }
        if (!replaced) {
            Log.info(log, "不可能 自定义参数处理器{} 没能替代默认处理器{}", processor.getClass().getName(), target.getName());
        }
        //重置
        adapter.setReturnValueHandlers(returnValueHandlerArrayList);
        return processor;
    }

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        Method method = returnType.getMethod();
        if (method == null) {
            return false;
        }
        Class<?> containingClass = returnType.getContainingClass();
        Class<?> resolveReturnType = GenericTypeResolver.resolveReturnType(method, containingClass);
        return (resolveReturnType.isAssignableFrom(Result.class) &&
                returnType.hasMethodAnnotation(ResponseBody.class));
    }

    @Override
    public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
                                  ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
            throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
        ResultMethodProcessor.formatResult(returnValue, webRequest);
        super.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
    }
}
